package bhwz.seac3.bl.import_.crawler;

import java.security.InvalidParameterException;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.BiConsumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class NBACrawler {
	private String seasonFrom;
	private String seasonTo;
	private Set<String> seasons; // 保存各个赛季数据的url

	public NBACrawler(String seasonFrom, String seasonTo) {
		this.seasonFrom = seasonFrom;
		this.seasonTo = seasonTo;
		checkSeason(seasonFrom,seasonTo);
		
	}

	/**
	 * get all seasons page link from baseUrl
	 * 
	 * @param baseUrl
	 */
	public void init(String baseUrl) {
		Downloader downloader = new Downloader();
		String html = downloader.download(baseUrl);
		HtmlParser parser = new HtmlParser();
		seasons = parser.filterLinks(html, baseUrl, "",
				s -> {
					Pattern p = Pattern.compile("\\d{4}-\\d{2}");
					Matcher m = p.matcher(s);
					return (m.matches()) && (s.compareTo(seasonFrom) >= 0)
							&& (s.compareTo(seasonTo) <= 0);
				});
	}

	public void crawling(String baseUrl, BiConsumer<String,String> consumer) {
		init(baseUrl);
		for (String season : seasons) {
			System.out.println(season);
			System.out.println("--------------------------");
			season = season.substring(0, season.lastIndexOf('.'))
					+ "_games.html";
			Downloader downloader = new Downloader();
			String html = downloader.download(season);
			HtmlParser parser = new HtmlParser();
			// find links under div 'div_games' and link text is "Box Score"
			Set<String> filteredLinks = parser.filterLinks(html, baseUrl,
					"#div_games ", s -> {
						return s.equals("Box Score");
					});
			UrlQueue.addUnvisitedUrls(filteredLinks);
			while (!UrlQueue.isUnVisitedUrlsEmpty()) {
				String url = UrlQueue.unVisitedUrlsDequeue();
				String html_game = downloader.download(url);
				consumer.accept(html_game,baseUrl);
			}
		}
	}

	public void concurrentCrawling(String baseUrl, BiConsumer<String,String> consumer) {
		ExecutorService fixedThreadPool = Executors.newFixedThreadPool(Runtime
				.getRuntime().availableProcessors());
		fixedThreadPool.execute(new Runnable() {
			@Override
			public void run() {
				crawling(baseUrl, consumer);
			}
		});
		fixedThreadPool.shutdown();
	}
	
	private void checkSeason(String... seasons){
		for(String season:seasons){
		Pattern p = Pattern.compile("\\d{4}-\\d{2}");
		Matcher m = p.matcher(season);
		if(m.matches()){
			int start = 0,end=0;
			try{
			start=Integer.parseInt(season.substring(2,4));
		    end=Integer.parseInt(season.substring(5,7));
			}catch (NumberFormatException e){
				e.printStackTrace();
				throw new InvalidParameterException();
				
			}
			if(end-start==1){
				return;
			}
		}
		throw new InvalidParameterException();
		}
	}
}
